
package com.yadong.smarthome2.protocol2.wificlient;

import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

import com.yadong.smarthome2.protocol2.RequestProtocol.Request;
import com.yadong.smarthome2.protocol2.ResultProtocol.Result;
import com.yadong.smarthome2.protocol2.client.DeviceInfoManager;
import com.yadong.smarthome2.protocol2.client.SendResultInterface;

public class SocketServerService extends Service implements
        NewMessageListener, NewRequestListener, SendResultInterface {
    private static final String TAG = "SocketServerService";
    private static final int SERVER_PORT = 10081;
    private static final int CLIENT_BROADCAST_THREAD_PORT = 10082;
    private static final int SERVER_PROADCAST_THREAD_PORT = 10083;

    private static final int HANDLER_MESSAGE_STOP_SERVICE = 1;
    private static final int HANDLER_MESSAGE_UPDATE_NOTIFICATION = 2;
    private static final int STOP_SERVICE_DELY = 10 * 1000; // Dely 10s to stop service.

    private BroadcastReceiveThread mClientBroadCastReceiverThread = null;
    private SocketServerConnectionThread mSocketServerThread = null;
    private List<NewMessageListener> mSocketServerMessageListeners = new ArrayList<NewMessageListener>();
    private List<NewRequestListener> mSocketServerRequestListeners = new ArrayList<NewRequestListener>();
    private NotificationManager mNotificationManager;
    private static final int NOTIFICATION_ID = 1;
    private DeviceInfoManager mDeviceInfoManager;

    public static Intent createServerInIntent(Context context) {
        Intent intent = new Intent(context, SocketServerService.class);
        return intent;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mClientBroadCastReceiverThread = new BroadcastReceiveThread(CLIENT_BROADCAST_THREAD_PORT);
        mClientBroadCastReceiverThread.setMessageListener(this);
        mSocketServerThread = new SocketServerConnectionThread("socket_connection_thread");
        mSocketServerThread.setNewMessageReceiveListener(this);
        Notification notification = new Notification();
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        startForeground(NOTIFICATION_ID, notification);
    }

    public void setDeviceInfoManager(DeviceInfoManager manager2) {
        this.mDeviceInfoManager = manager2;
    }

    public void addSocketServerMessageListener(NewMessageListener listener) {
        if (listener == null) {
            return;
        }
        synchronized (mSocketServerMessageListeners) {
            mSocketServerMessageListeners.add(listener);
        }
    }

    public void removeSocketServerMessageListener(NewMessageListener listener) {
        synchronized (mSocketServerMessageListeners) {
            mSocketServerMessageListeners.remove(listener);
        }
    }

    public void addSocketServerRequestListener(NewRequestListener listener) {
        if (listener == null) {
            return;
        }
        synchronized (mSocketServerRequestListeners) {
            mSocketServerRequestListeners.add(listener);
        }
    }

    public void removeSocketServerRequestListener(NewRequestListener listener) {
        synchronized (mSocketServerRequestListeners) {
            mSocketServerRequestListeners.remove(listener);
        }
    }

    private void publishNewRequest(Request request) {
        synchronized (mSocketServerRequestListeners) {
            for (NewRequestListener listener : mSocketServerRequestListeners) {
                listener.onNewMessageReceived(null, request);
            }
        }
    }

    private void publishNewMessage(String message) {
        synchronized (mSocketServerMessageListeners) {
            for (NewMessageListener listener : mSocketServerMessageListeners) {
                listener.onNewMessageReceived(null, message);
            }
        }
    }

    public void sendDataToClient(Result data) {
        Log.v(TAG, "send message to target data = " + data + " mSocketServerThread.isConnected()="
                + mSocketServerThread.isConnected());
        if (mSocketServerThread.isConnected()) {
            try {
                mSocketServerThread.sendDataToClient(data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onNewMessageReceived(String threadName, String message) {
        System.out.println("onNewMessageReceived..." + message);
        if (TextUtils.equals(threadName, mClientBroadCastReceiverThread.getName())) {
            String currentIp = null;
            try {
                currentIp = Utils.getLocalHostIp();
            } catch (SocketException e) {
                e.printStackTrace();
            }
            // 發送廣播 包括 當前IP地址:開放端口,設備名稱,mac地址
            new BroadcastSenderTask(null).execute(SERVER_PROADCAST_THREAD_PORT + "", currentIp
                    + ":" + SERVER_PORT + ",Telephone," + getWifiMacAddress());
        } else if (TextUtils.equals(threadName, mSocketServerThread.getName())) {

        }
    }

    public static String getWifiMacAddress() {
        try {
            String interfaceName = "wlan0";
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface
                    .getNetworkInterfaces());
            for (NetworkInterface intf : interfaces) {
                if (!intf.getName().equalsIgnoreCase(interfaceName)) {
                    continue;
                }

                byte[] mac = intf.getHardwareAddress();
                if (mac == null) {
                    return "";
                }

                StringBuilder buf = new StringBuilder();
                for (byte aMac : mac) {
                    buf.append(String.format("%02X:", aMac));
                }
                if (buf.length() > 0) {
                    buf.deleteCharAt(buf.length() - 1);
                }
                return buf.toString();
            }
        } catch (Exception ex) {
        } // for now eat exceptions
        return "";
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Connected to wifi, start server listener.
        // Setup1. Start socket server thread. wait for connection.
        Log.d(TAG, " ServerIn socketServerThread isAlive = " + mSocketServerThread.isAlive()
                + " connected=" + mSocketServerThread.isConnected());
        if (!mSocketServerThread.isAlive() && !mSocketServerThread.isConnected()) {
            mSocketServerThread.start();
        }

        Log.d(TAG, " ServerIn mClientBroadCastReceiverThread isAlive = "
                + mClientBroadCastReceiverThread.isAlive()
                + " connected=" + mClientBroadCastReceiverThread.isThreadRuning());
        // Setup2. Start listening to client broadcast.
        if (!mClientBroadCastReceiverThread.isAlive()) {
            mClientBroadCastReceiverThread.start();
        }

        // Setup3. Send broadcast to client, tell the client the server's ip
        // and port.
        String currentIp = null;
        try {
            currentIp = Utils.getLocalHostIp();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        new BroadcastSenderTask(null).execute(SERVER_PROADCAST_THREAD_PORT + "", currentIp
                + ":" + SERVER_PORT + ",Telephone," + getWifiMacAddress());
        // Exit the service,but disconnected the socket first.
        return super.onStartCommand(intent, flags, startId);
    }

    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            int what = msg.what;
            switch (what) {
                case HANDLER_MESSAGE_STOP_SERVICE:
                    stopSelf();
                    break;
                case HANDLER_MESSAGE_UPDATE_NOTIFICATION:

                    break;
                default:
                    break;
            }
        };
    };

    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    public class MyBinder extends Binder {
        public SocketServerService getService() {
            return SocketServerService.this;
        }
    }

    @Override
    public void onNewMessageReceived(String threadName, Request request) {
        System.out.println("onNewMessageReceived .. " + request);
        mDeviceInfoManager.handleDeviceInfoRequest(request, this);
        publishNewMessage(request.getTag());
        publishNewRequest(request);
    }

    @Override
    public void sendResult(Result result) {
        sendDataToClient(result);
    }

}
